﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using Jurassic_Island;
using System.Data;
using System.Collections;


namespace JurassicIslandWeb.MapFiles
{
    public class Linea
    {
        private Point origen;
        private Point destino;

        public int Longitud
        {   //distancia=raizcuadrada( (x2 - x1) ^ 2 + (y2 - y1) ^ 2 )
            get { 
                return (int)Math.Sqrt(Math.Pow(Math.Abs(destino.X - origen.X), 2) + Math.Pow(Math.Abs(destino.Y - origen.Y), 2)); 
            }
        }

        public Point Origen
        {
            get { return origen; }
            set { origen = value; }
        }

        public Point Destino
        {
            get { return destino; }
            set { destino = value; }
        }

        public Linea()
        {
            origen = new Point(0, 0);
            destino = new Point(0, 0);
        }

        public Linea(Point p_orig, Point p_dest)
        {
            origen = p_orig;
            destino = p_dest;
        }

        public Linea(Linea l)
        {
            origen = l.origen;
            destino = l.destino;
        }

        public Linea(int x_orig, int y_orig, int x_dest, int y_dest)
        {
            origen = new Point(x_orig, y_orig);
            destino = new Point(x_dest, y_dest);
        }
        
    }

    public partial class dynImgMapExplo : System.Web.UI.Page
    {
        private String rutaMapa = "~/MapFiles/mapa.png";
        private String rutaExplo = "~/MapFiles/explorador.gif";
        private String rutaBoton = "~/MapFiles/botonDino.gif";

        //Tamaño total del mapa. La relación de aspecto de mapa es de 4:3
        private Point tamMapa = new Point(2000, 1500);

        // Tamaño por defecto del trozo de mapa que se coge
        private Point tamTrozo = new Point(400, 300);

        protected void Page_Load(object sender, EventArgs e)
        {
            // Aplicamos zoom al trozo de imagen (1 deja la imagen igual)
            PointF tamD = tamMapa;
            Double zoom = obtenerParametroDouble("zoom", 1);
            tamMapa.X = Convert.ToInt32(tamD.X * zoom);
            tamMapa.Y = Convert.ToInt32(tamD.Y * zoom);

            //img carga el mapa
            Bitmap imgOriginal = new Bitmap(Server.MapPath(rutaMapa));
            Bitmap imgExplorador = new Bitmap(Server.MapPath(rutaExplo));
            Bitmap imgBoton = new Bitmap(Server.MapPath(rutaBoton));

            Int32 exploX = obtenerParametroEntero("x", 0);
            if (exploX > (tamMapa.X - imgExplorador.Width))
            {
                exploX = (tamMapa.X - imgExplorador.Width);
            }
            Int32 exploY = obtenerParametroEntero("y", 0);
            if (exploY > (tamMapa.Y - imgExplorador.Height))
            {
                exploY = (tamMapa.Y - imgExplorador.Height);
            }
            exploX -= 10;
            exploY -= 32;

            // Obtenemos el ancho de la imagen a devolver
            Int32 coW = obtenerParametroEntero("w", tamTrozo.X);
            if (coW > tamMapa.X)
                coW = tamMapa.X;

            // Obtenemos el alto de la imagen a devolver
            Int32 coH = obtenerParametroEntero("h", tamTrozo.Y);
            if (coH > tamMapa.Y)
                coH = tamMapa.Y;

            // Obtenemos el valor de la coordenada X de la porción de mapa a obtener
            Int32 coX = exploX - (coW / 2);
            if (coW < tamMapa.X)
            {
                if (coX > (tamMapa.X - coW))
                {
                    coX = (tamMapa.X - coW);
                } else if (coX < 0)
                {   coX = 0; }
            } else {coX = 0;}
            //coX -= 10;

            // Obtenemos el valor de la coordenada Y de la porción de mapa a obtener
            /*Int32 coY = exploY - (coH / 2);
            if (coY > (tamMapa.Y - tamTrozo.Y))
            {
                coY = (tamMapa.Y - tamTrozo.Y);
            } else if (coY < 0)
            {   coY = 0; }*/
            Int32 coY = exploY - (coH / 2);
            if (coH < tamMapa.Y)
            {
                if (coY > (tamMapa.Y - coH))
                {
                    coY = (tamMapa.Y - coH);
                }
                else if (coY < 0)
                { coY = 0; }
            }
            else { coY = 0; }
            //coY -= 32;

            
            // objImageTemp ajusta el tamaño de la imagen
            Bitmap imgTemp = new Bitmap(imgOriginal, tamMapa.X, tamMapa.Y);

            // g2 lo usaremos para pintar caminos y lugares antes de recortar
            Graphics g2 = Graphics.FromImage(imgTemp);

            //Ahora pintamos las lineas correspondientes a los caminos
            try
            {
                ArrayList caminos = obtenerCaminos();
                Pen lapiz = new Pen(Color.FromKnownColor(KnownColor.Brown), 5);
                lapiz.EndCap = LineCap.ArrowAnchor;

                foreach (Linea lin in caminos)
                {
                    g2.DrawLine(lapiz, lin.Origen, lin.Destino);
                }

                foreach (Linea lin in caminos)
                {
                    /* Para pintar las flechas de direccion azules*/
                    Pen lapiz2 = new Pen(Color.FromKnownColor(KnownColor.Blue), 10);
                    float[] numeros = { 0.1F, 1000.0F };
                    lapiz2.DashPattern = numeros;
                    lapiz2.EndCap = LineCap.ArrowAnchor;
                    Point ap = new Point();
                    ap.X = lin.Origen.X - (lin.Origen.X - lin.Destino.X) / 5;
                    ap.Y = lin.Origen.Y - (lin.Origen.Y - lin.Destino.Y) / 5;
                    g2.DrawLine(lapiz2, lin.Origen, ap);
                }
            }
            catch (Exception)
            {
            }

            // Pintamos sobre el bitmap temporal los puntos de los lugares
            try
            {
                Rectangle recorteBoton = new Rectangle(0, 0, imgBoton.Width, imgBoton.Height);
                DataTable dtLugares = obtenerLugares();
                foreach (DataRow drLugar in dtLugares.Rows)
                {
                    int btlX = int.Parse(drLugar["Coordenada X"].ToString()) - 15;
                    int btlY = int.Parse(drLugar["Coordenada Y"].ToString()) - 15;

                    g2.DrawImage(imgBoton, btlX, btlY, recorteBoton, GraphicsUnit.Pixel);
                }
            }
            catch (Exception)
            {
            }

            // bm será el lienzo para el trozo de imagen que extraigamos
            Bitmap lienzo = new Bitmap(coW, coH);

            //g es el objeto gráfico que nos 
            Graphics g = Graphics.FromImage(lienzo);

            Rectangle recorte = new Rectangle(coX, coY, coW, coH);
            Rectangle recorteExplo = new Rectangle(0, 0, imgExplorador.Width, imgExplorador.Height);
            
            g.DrawImage(imgTemp, 0, 0, recorte, GraphicsUnit.Pixel);
            g.DrawImage(imgExplorador, exploX-coX, exploY-coY, recorteExplo, GraphicsUnit.Pixel);
            

            Bitmap imgSalida = lienzo;

            Response.ContentType = "image/png"; //con esto decimos que el tipo de datos devuelto corresponde a una imagen PNG
            imgSalida.Save(Response.OutputStream, ImageFormat.Png);
            imgSalida.Dispose();
        }

        private DataTable obtenerLugares()
        {
            ENLugares enLug = new ENLugares();
            DataSet dsLugares = new DataSet();
            dsLugares = enLug.ObtenerListaLugares();
            return dsLugares.Tables["Lugares"];
        }

        private ArrayList obtenerCaminos()
        {
            ArrayList arrayLineas = new ArrayList();

            try
            {
                ENCaminos enCam = new ENCaminos();
                ENLugares enLug = new ENLugares();

                DataSet dsCaminos = new DataSet();
                DataSet dsLugares = new DataSet();

                dsCaminos = enCam.ObtenerListaCaminos();
                dsLugares = enLug.ObtenerListaLugares();

                foreach (DataRow drCam in dsCaminos.Tables["Caminos"].Rows)
                {
                    DataRow drLugOrig = dsLugares.Tables["Lugares"].Rows.Find(drCam["Origen"].ToString());
                    DataRow drLugDest = dsLugares.Tables["Lugares"].Rows.Find(drCam["Destino"].ToString());

                    Point Orig = new Point(int.Parse(drLugOrig["Coordenada X"].ToString()),
                                          int.Parse(drLugOrig["Coordenada Y"].ToString()));

                    Point Dest = new Point(int.Parse(drLugDest["Coordenada X"].ToString()),
                                          int.Parse(drLugDest["Coordenada Y"].ToString()));

                    Linea lin = new Linea(Orig, Dest);
                    arrayLineas.Add(lin);
                }
            }
            catch (Exception)
            {
            }

            return arrayLineas;
            
        }

        private int obtenerParametroEntero(String parametro, int valorDefault)
        {
            int num = 0;

            try
            {
                num = Convert.ToInt32(Request.QueryString.Get(parametro));
            }
            catch (Exception) { }

            if (num <= 0)
            {
                num = Convert.ToInt32(valorDefault);
            }

            return num;
        }

        private Double obtenerParametroDouble(String parametro, Double valorDefault)
        {
            Double num = 0;

            try
            {
                num = Double.Parse(Request.QueryString.Get(parametro));
            }
            catch (Exception) { }

            if (num <= 0)
            {
                num = valorDefault;
            }

            return num;
        }
    }
}